import { Loading } from "element-ui";
import Message from "./Message";
import router from "../router";
import md5 from "js-md5";

function openLoading() {
  return Loading.service({
    lock: true,
    text: "拼命加载中...",
    spinner: "el-icon-loading",
    background: "rgba(0, 0, 0, 0.7)",
  });
}
class Shios {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
    this.message = new Message();
    this.data = JSON.parse(window.sessionStorage.getItem("token"));
    this.caches = {};
    this.token = {};
  }
  joinUrl(action, id, isGet) {
    if (!isGet) {
      let cacheName = (/(?<=\/api\/)\w+/).exec(action);
      // this.caches.delete(cacheName);
      delete this.caches[cacheName];
    }
    let url = `${this.baseUrl}${action}`;

    if (typeof id === "object") {
      let args = action.includes("?") ? "&" : "?";
      for (const key in id) {
        if (Object.hasOwnProperty.call(id, key)) {
          if (id[key] === 0 || id[key]) {
            args += `${key}=${id[key]}&`;
            // args += `${key}=${window.encodeURIComponent(id[key])}&`;
          }
        }
      }
      args = args.substring(0, args.length - 1);
      url += args;
    } else {
      url += `${id ? "/" + id : ""}`;
    }
    return url;
  }
  randomString(e) {
    e = e || 32;
    const t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
    const a = t.length;
    let n = "";
    for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));
    return n;
  }
  bodyToString(bodyStr) {
    if (typeof bodyStr !== "string") {
      return "";
    }
    if (!bodyStr) {
      return "";
    }

    let data = "";
    try {
      data = JSON.parse(bodyStr);
    } catch (error) {
      console.error(error);
      return "";
    }
    if (!data) {
      return "";
    }
    if (typeof data === "object") {
      let str = "";
      for (const key in data) {
        if (Object.hasOwnProperty.call(data, key)) {
          str += key + String(data[key]);
        }
      }
      return str;
    } else {
      return String(data);
    }
  }
  encodeURIComponent(url) {
    let index = url.lastIndexOf("?");
    if (index === -1) {
      return url;
    }
    let component = url.slice(index + 1);
    let baseUrl = url.slice(0, index + 1);
    console.log(baseUrl);
    component = window.encodeURIComponent(component);
    console.log(component);
    return baseUrl + component;
  }
  urlToString(url = "") {
    let index = url.lastIndexOf("?");
    if (index === -1) {
      return "";
    }
    let argsStr = url.slice(index + 1);
    argsStr = argsStr.replace(/[\\=\\&]/gi, ""); // name=2 => name2
    return argsStr;
  }
  encrypt(url, body) {
    if (!this.data) {
      return;
    }
    const timeStamp = "1624342875394" || Date.now();
    const nonce = "abcd" || this.randomString(6);
    let signature = "";
    // 拼接签名数据
    let signStr =
      timeStamp +
      nonce +
      this.data.UserId +
      this.data.SignToken +
      this.urlToString(url) +
      this.bodyToString(body);

    const arr = signStr.split("");
    signStr = arr.sort((a, b) => a.localeCompare(b, "zh-CN")).join("");

    signature = md5(signStr).toUpperCase();
    this.token = {
      userid: this.data.UserId || "",
      timestamp: timeStamp,
      nonce,
      signature,
    };
    // 将字符串中字符按升序排序
    // const sortStr = string.Concat(signStr.OrderBy(c => c));
    // var bytes = Encoding.UTF8.GetBytes(sortStr);
    // //使用MD5加密
    // var md5Val = hash.ComputeHash(bytes);
    // //把二进制转化为大写的十六进制
    // StringBuilder result = new StringBuilder();
    // foreach (var c in md5Val)
    // {
    //     result.Append(c.ToString("X2"));
    // }
  }
  async myFetch(...args) {
    let url = args[0];
    this.encrypt(url, args[1].body);
    args[1].headers = {
      ...args[1].headers,
      ...this.token,
    };
    // args[0] = this.encodeURIComponent(url);
    try {
      let response = await fetch(...args);
      switch (response.status) {
        case 401:
          router.push("/Login");
          window.sessionStorage.clear();
          this.message.error("登录超时，请重新登录");
          break;
        case 403:
          this.message.error("权限不足，请确认当前用户是否有足够访问权限");
          break;

        default:
          break;
      }
      if (response.status != 204) {
        response.data = await response.json();
      }
      if (!response.ok) {
        throw response;
      } else if (response.data.Code != 200) {
        this.message.error(response.data.Message);
        throw response;
      } else {
        return response;
      }
    } catch (error) {
      if (!error.status) {
        this.message.error("请求失败,服务器无响应");
      }
      // else {
      //   console.error(error);
      //   // router.push("/Login");
      // }
      throw error;
    }
  }
  async get(action = "", id) {
    let cacheName = (/(?<=api\/)\w+/).exec(action)[0];
    let url = this.joinUrl(action, id, true);
    if (this.caches[cacheName] && url in this.caches[cacheName]) {
      // console.log(123);
      return this.caches[cacheName][url];
    }
    // console.log(456);
    let response = await this.myFetch(url, {
      method: "GET",
      headers: {
        Accept: "application/json",
      },
    });
    if (!(/Common/i).test(cacheName)) {
      this.caches[cacheName] = { ...this.caches[cacheName], [url]: response };
    }
    return response;
  }
  async Get(url = "", id) {
    // const loading = openLoading();
    return this.get(url, id);

    // finally {
    //   //loading.close();
    // }
  }
  async post(action = "", data, id) {
    // const loading = openLoading();
    let url = this.joinUrl(action, id);

    const response = await this.myFetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    });
    if (typeof response.data.Data !== "string") {
      this.message.success(response.data.Message);
    }
    return response;
  }
  async upload(action = "", formData, id) {
    // const loading = openLoading();
    let url = this.joinUrl(action, id);
    return await this.myFetch(url, {
      method: "POST",
      body: formData,
    });
  }
  async Put(url = "", item) {
    if (!item) {
      throw `item is ${item}`;
    }
    // const loading = openLoading();
    url = `${this.baseUrl}${url}`;

    return await this.myFetch(url, {
      method: "PUT",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        userId: this.userId,
        token: this.data.token,
      },
      body: JSON.stringify(item),
    });
  }
  async Patch(url = "", item, id) {
    if (!id) {
      throw "id 为空";
    }

    if (!item) {
      throw `item is ${item}`;
    }
    // const loading = openLoading();
    url = `${this.baseUrl}${url}${id ? "/" + id : ""}`;

    let response = await this.myFetch(url, {
      method: "PATCH",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        userId: this.userId,
        token: this.data.token,
      },
      body: JSON.stringify(item),
    });

    if (response.ok) {
      return response;
    }
    throw response;
  }
  async Delete(url = "", id) {
    return this.delete(url, id);
  }
  async delete(action = "", id) {
    let url = this.joinUrl(action, id);
    const loading = openLoading();

    try {
      let response = await this.myFetch(url, {
        method: "DELETE",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      });
      if (response.ok) {
        this.message.success(response.data.Message);
        return response;
      }
      throw response;
    } finally {
      loading.close();
    }
  }
  static install(Vue) {
    Vue.prototype.$http = new Shios(process.env.VUE_APP_BASEURL);
  }
}

export default Shios;
